﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Collections;
using System.Threading;
using System.Security.Cryptography;
using System.IO;

namespace HomeTask03
{
  //  true if managed resources should be disposed; otherwise, false.

    
    public partial class Form1 : Form
    {
        public delegate void pbIncrement(String name);
        public pbIncrement PbInc;
        public delegate void JpStatusDelegate(String name, String status,Boolean err);
        public JpStatusDelegate jpStatus;
        private SortedList jobList;
        private string jobName;
        private int namber;
        private string NAME = "Job №";
        private Boolean isDecrypt; //false : Encrypt; true : Decrypt
        
        private string Password = "dz6yhdkrgh";
        private Rijndael algPass;
        
        private string[] STATUS_STR = {
                                      "Source path  is not defined!",
                                      "Destination path  is not defined!",
                                      "There is not any job!",
                                      "There is not any selected!"
                                      }; 
 
        public Form1()
        {
            InitializeComponent();
            initData();
            PbInc = new pbIncrement(ProgressBarIncrement);
            jpStatus = new JpStatusDelegate(JobsPanelStatus);
            algPass = EncriptPassword();



        }

        /// <summary>
        /// Preparation of string of the password
        /// </summary>
        private Rijndael EncriptPassword()
        {
            PasswordDeriveBytes pdb = new PasswordDeriveBytes(Password, new byte[] {0x34, 0x28, 0x76, 0x6f, 0x33, 0x5d, 
            0x94, 0x37, 0x2d, 0x7c, 0x3d, 0x44, 0x24});

            Rijndael alg = Rijndael.Create();
            alg.Key = pdb.GetBytes(32);
            alg.IV = pdb.GetBytes(16);
            return alg;
        }


        private void initData()
        {
        openFileDialog1.InitialDirectory = Application.ExecutablePath;
        saveFileDialog1.InitialDirectory = Application.ExecutablePath;
        jobList = new SortedList();
        namber = 1;
        isDecrypt = false;
        }

        /// <summary>
        /// is used for access to the Progress Bar by the use of delegate
        /// </summary>
        /// <param name="name">Name of task</param>
        public void ProgressBarIncrement(string name)
        {
           ((JobPanel)jobList[name]).setProgress();   

        }

        /// <summary>
        /// is used for access to the JobPanel by the use of delegate
        /// </summary>
        /// <param name="name">Name of task</param>
        /// <param name="status">Message string</param>
        /// <param name="err">true if error; otherwise, false.</param>
        public void JobsPanelStatus(string name, string status, Boolean err)
         {

             ((JobPanel)jobList[name]).setStatusColor(" Snatus: " + status,err);
             if (err) { ((JobPanel)jobList[name]).jobThread.Abort(); }
             
         }
 
        
        private void btnSource_Click(object sender, EventArgs e)
        {
            SelectSourcePach();
        }

        /// <summary>
        /// selecting and preparation of the source file path. 
        /// </summary>
        private void SelectSourcePach()
        {
            int count;
            Boolean isDecr;
            String str;
            String newfilepath;
            if (openFileDialog1.ShowDialog() == DialogResult.OK)
            {
                tbSourcePath.Lines = openFileDialog1.FileNames;
                count = tbSourcePath.Lines.Length;
                if (count <= 0) return;
                if (count == 1)
                {
                    isDecr = isResolvType(tbSourcePath.Lines[0]);
                    rbEncrypt.Checked = !isDecr;
                    rbDecrypt.Checked = isDecr;
                    isDecrypt = isDecr;
                    tbDestinationPath.Text = BuildFileName(tbSourcePath.Lines[0], isDecr);
                }
                if (count > 1)
                {
                    str = "";
                    for (int i = 0; i < count; i++)
                    {
                        isDecr = isResolvType(tbSourcePath.Lines[i]);
                        newfilepath = BuildFileName(tbSourcePath.Lines[i], isDecr);
                        str += newfilepath + "\r\n";
                    }
                    str = str.Remove(str.Length - 2);
                    tbDestinationPath.Text = str;

                    tbDestinationPath.Enabled = false;
                    btnDestination.Enabled = false;

                }

            }
        }


 
        /// <summary>
        /// preparation of the destination file name.
        /// </summary>
        /// <param name="filepath">Full file path</param>
        /// <param name="isDecr">true if decrypt; otherwise, false.</param>
        private String BuildFileName(String filepath, Boolean isDecr)
        {
            String ext;
            ext = isDecr ? ".txt" : ".out";
            String filePath = Path.ChangeExtension(filepath, ext);
            return filePath;
        }


        private void btnDestination_Click(object sender, EventArgs e)
        {
            if (saveFileDialog1.ShowDialog() == DialogResult.OK)
            {
             
                tbDestinationPath.Text = saveFileDialog1.FileName;
            }
        }


        private void btnAddJob_Click(object sender, EventArgs e)
        {
            addJobItem();
        }

        /// <summary>
        /// adding new job and new JobPanel; 
        /// </summary>
        private void addJobItem()
        {
            String SourcePath, DestinationPath;
            Boolean isDecr;
            int count;
            RemoveJobIsComplete();
            jobListPreview();
            toolStripStatusLabel.Text = "";

            if (tbSourcePath.Lines.Length <= 0) { toolStripStatusLabel.Text = STATUS_STR[0]; return; }
            if (tbDestinationPath.Lines.Length <= 0) { toolStripStatusLabel.Text = STATUS_STR[1]; return; }
            count = tbSourcePath.Lines.Length;
            if (count == 1)
            {
                SourcePath = tbSourcePath.Text;
                DestinationPath = tbDestinationPath.Text;
                isDecr = isDecrypt;
                addOneJob(SourcePath, DestinationPath, isDecr);
            }
            else
            {

                for (int i = 0; i < count; i++)
                {
                    isDecr = isResolvType(tbSourcePath.Lines[i]);
                    SourcePath = tbSourcePath.Lines[i];
                    DestinationPath = tbDestinationPath.Lines[i];
                    addOneJob(SourcePath, DestinationPath, isDecr);
                }
            }
            jobListPreview();

            tbDestinationPath.Enabled = true;
            btnDestination.Enabled = true;
            tbSourcePath.Text = "";
            tbDestinationPath.Text = ""; 
        }

        /// <summary>
        /// define type of executable operation on file extension.
        /// </summary>
        /// <param name="filepath">Full file path</param>
         protected Boolean isResolvType(String filepath)
        {
            String ext = Path.GetExtension(filepath);
            if (ext == ".txt") { return false; }
            if (ext == ".out") { return true; }
            return isDecrypt;
        }


        private void addOneJob(String SourcePath,String DestinationPath, Boolean isDecr)
        {
            jobName = NAME + namber;
            namber++;
            JobPanel jp = new JobPanel(jobName, SourcePath, DestinationPath, isDecr);
            jobList.Add(jobName, jp);
        }

        /// <summary>
        /// Update of view of the list of jobs.
        /// </summary>
        private void jobListPreview() 
        {
            
            int n;
            JobPanel jp;
            panAllJobs.Controls.Clear();
            ICollection c = jobList.Keys;
            foreach (string name in c)
            {
                jp = (JobPanel)jobList[name];
                panAllJobs.Controls.Add(jp);
                n = panAllJobs.Controls.Count;
                jp.Top = 2 + (109 * (n - 1));
                jp.Visible = true;
            }
            
        }

        private void btnRunAllJobs_Click(object sender, EventArgs e)
        {
            JobPanel jp;
            toolStripStatusLabel.Text = "";
            RemoveJobIsComplete();
            jobListPreview(); 
            if (jobList.Count == 0) { toolStripStatusLabel.Text = STATUS_STR[2]; return; }
            ICollection c = jobList.Keys;
            foreach (string name in c)
            {
                jp = (JobPanel)jobList[name];
                EncodeThread ethrd = new EncodeThread(this, name,jp, algPass);
                Thread thrd = new Thread(ethrd.Run);
                thrd.Start();
                jp.jobThread = thrd;
            }
            tbDestinationPath.Enabled = true;
            btnDestination.Enabled = true;
        }

        private void btnDeleteSelected_Click(object sender, EventArgs e)
        {
            toolStripStatusLabel.Text = "";
            if (jobList.Count == 0) { toolStripStatusLabel.Text = STATUS_STR[2]; return; }
            RemoveJob();
            jobListPreview(); 

        }

        /// <summary>
        /// Removal of the selected jobs.
        /// </summary>
        private void RemoveJob()
        {
            ICollection c = jobList.Keys;
            foreach (string name in c)
            {
                if (((JobPanel)jobList[name]).isSelected())
                {
                    jobList.Remove(name);
                    RemoveJob();
                    break;
                }
                
            }
        }

        /// <summary>
        /// Removal of the completed jobs.
        /// </summary>
        private void RemoveJobIsComplete()
        {
            ICollection c = jobList.Keys;
            foreach (string name in c)
            {
                if (((JobPanel)jobList[name]).isComplete)
                {
                    jobList.Remove(name);
                    RemoveJobIsComplete();
                    break;
                }

            }
        }


        private void rbEncrypt_CheckedChanged(object sender, EventArgs e)
        {
            isDecrypt = false;
        }

        private void rbDecrypt_CheckedChanged(object sender, EventArgs e)
        {
            isDecrypt = true;
        }



 
    }
}
